package net.oktaeder.office.utils.ordertransformer;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;

import net.oktaeder.office.model.Employee;
import net.oktaeder.office.model.Model;
import net.oktaeder.office.model.WorkOrder;
import net.oktaeder.office.view.Mail;
import net.oktaeder.office.view.MailDaemon;
import net.oktaeder.office.simulation.Simulation;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * This class is capable of transforming textual messages into
 * internal order structure.
 * 
 * @author tuukka
 *
 */
public class OrderTransformer {

	private static Log log = LogFactory.getLog(OrderTransformer.class);
	
	IMailTransformer systemMails;
	IMailTransformer personalMails;
	IMailTransformer labourMarketMails;
	
	public OrderTransformer() {
		log.trace("Creating an instance");
		systemMails = new SystemMailTransformer();
		personalMails = new PersonalMailTransformer();
		labourMarketMails = new LabourMarketMailTransformer();
	}
	
	/**
	 * Transform mails into orders and dispatch them
	 *
	 */
	public void transformMails() throws Exception {
		MailDaemon mailDaemon;
		try {
			mailDaemon = Simulation.getInstance().getMailDaemon();
			Iterator<Mail> iterator = mailDaemon.iterator();
			Mail mail;
			
			while (iterator.hasNext()) {
				mail = iterator.next();
				if (StringUtils.indexOf(mail.getRecepient(), "system") == 0) {
					//direct mail to the system transformer
					DeliverOrders(systemMails.TransformMail(mail));
					//mark the mail for deletion					
					mail.setDeletion(true);
				} else if (StringUtils.indexOf(mail.getRecepient(), "labour-market") == 0) {
					//direct mail to the labour market transformer
					DeliverOrders(labourMarketMails.TransformMail(mail));
					//mark the mail for deletion					
					mail.setDeletion(true);					
				} else { 
					DeliverOrders(personalMails.TransformMail(mail));
					mail.setDeletion(true);
				}
			}
			
		} catch (Exception ex) {
			log.error("Error while transforming mails", ex);
			throw new Exception("Error while transforming mails", ex);
		}
	}
	
	/**
	 * Delivers orders to characters in the model
	 * 
	 * @param orders Orders to be delivered
	 */
	private void DeliverOrders(Hashtable<String, ArrayList<WorkOrder>> orders) {
		try {
			Enumeration<String> orderSetKeys;
			ArrayList<WorkOrder> workOrders;
			WorkOrder order;
			Iterator<WorkOrder> workOrderIterator;
			String key;
			Employee employee;

			if (orders != null) {

				orderSetKeys = orders.keys();

				while (orderSetKeys.hasMoreElements()) {
					key = orderSetKeys.nextElement();
					workOrders = orders.get(key);

					workOrderIterator = workOrders.iterator();

					while (workOrderIterator.hasNext()) {
						order = workOrderIterator.next();
						//now find where to deliver this specific order
						if (key.equals("system")) {
							Simulation.getInstance().receiveSystemMail(order);
						} else if (key.equals("labour-market")) {
							Simulation.getInstance().getLabourMarket().receiveMail(order);
						} else {
							employee = Model.getInstance().getCompany().getEmployeeByName(key);
							if (employee != null) {
								employee.addOrder(order);
							} else {
								//TODO: handle properly
								log.info("Mail recipient unknown: " + key);
							}
						}
					}
				}
			} else {
				log.warn("Tried to process 0 amount of orders");
			}

		} catch (Exception ex) {
			// log error and try to resume normal course of action
			log.error("Order delivery failed", ex);
		}
	}	
}